/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * EvaluationView.java
 *
 * Created on Oct 23, 2012, 11:53:22 PM
 */

package br.usp.ime.faguilar.guis;

import br.usp.ime.faguilar.classification.Classifible;
import br.usp.ime.faguilar.classification.ClassificationResult;
import br.usp.ime.faguilar.classification.Classifier;
import br.usp.ime.faguilar.classification.ShapeContextClassifier;
import br.usp.ime.faguilar.conversion.InkMLInput;
import br.usp.ime.faguilar.conversion.MathExpressionGraph;
import br.usp.ime.faguilar.data.DStroke;
import br.usp.ime.faguilar.data.TimePoint;
import br.usp.ime.faguilar.directories.MathRecognitionFiles;
import br.usp.ime.faguilar.export.InkMLExpression;
import br.usp.ime.faguilar.export.MathExpressionSample;
import br.usp.ime.faguilar.feature_extraction.PreprocessingAlgorithms;
import br.usp.ime.faguilar.graphics.GMathExpression;
import br.usp.ime.faguilar.graphics.GraphicalStrokeKruskalMST;
import br.usp.ime.faguilar.parser.BSTBuilder;
import br.usp.ime.faguilar.segmentation.Segmentation;
import br.usp.ime.faguilar.segmentation.SegmentationResult;
import br.usp.ime.faguilar.segmentation.TreeSearchSegmentation;
import br.usp.ime.faguilar.util.FilesUtil;
import br.usp.ime.faguilar.util.SymbolUtil;
import edu.princeton.cs.algs4.Edge;
import edu.princeton.cs.algs4.EdgeWeightedGraph;
import edu.princeton.cs.algs4.KruskalMST;
import java.awt.geom.Point2D;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import javax.swing.DefaultListModel;

/**
 *
 * @author frank
 */
public class EvaluationView extends javax.swing.JPanel {

    private Segmentation segmentation;
    private String SelectedFileName;

    private KruskalMST mst;
    private EdgeWeightedGraph StrokeSetToEdgeWeightedGraph;
    private Classifier classifier;
    private ArrayList<DStroke> strokes;

    private boolean fileSelected;
    /** Creates new form EvaluationView */
    public EvaluationView() {
        initComponents();
        localInitialization();
//        chargeFileNames();
    }

    private void localInitialization() {
        chargeFileNames();
        ArrayList<Classifible> classifibles = 
//                SymbolUtil.readTemplatesFromObjectFile("data/train_crohme_2012");
        SymbolUtil.readTemplatesFromInkmlFiles(
                MathRecognitionFiles.TRAINING_FILES_CROHME,
                MathRecognitionFiles.INKML_CROHME_2012_TRAIN_DIR);//SymbolUtil.readTemplatesWithStrokesInfo();//SymbolUtil.readTemplates();//SymbolUtil.readSymbolData(TEMPLATES_FILE);
        classifier = new ShapeContextClassifier();
        classifier.setTrainingData(classifibles);
        classifier.train();
//        segmentation =  new TreeSearchSegmentation(); //new Segmentation();
//        segmentation.setClassifier(classifier);
        fileSelected = false;
    }
    
    private void chargeFileNames(){
        SymbolUtil.FILES = MathRecognitionFiles.TEST_FILES_CROHME;
        SymbolUtil.FILES_FOLDER = MathRecognitionFiles.INKML_CROHME_2012_TEST_DIR;
        String[] files = SymbolUtil.readFilesNamesInAFile();
//                EvaluationView.TEST_FILES_CROHME);
//        String[] files = SymbolUtil.readFilesNamesInAFile(EvaluationView.TEST_FILES_CROHME);
        ArrayList<String> inkFiles = new  ArrayList();
        inkFiles.addAll(Arrays.asList(files));
        Collections.sort(inkFiles);
        DefaultListModel listModel = new DefaultListModel();
        for (String string : inkFiles) {
            listModel.addElement(string);
        }
        fileNames.setModel(listModel);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSplitPane1 = new javax.swing.JSplitPane();
        jPanel2 = new javax.swing.JPanel();
        jPanel5 = new javax.swing.JPanel();
        jSplitPane2 = new javax.swing.JSplitPane();
        jPanel6 = new javax.swing.JPanel();
        jPanel4 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        distanceFilter = new javax.swing.JCheckBox();
        mstFilter = new javax.swing.JCheckBox();
        showMST = new javax.swing.JCheckBox();
        useTree = new javax.swing.JCheckBox();
        jScrollPane3 = new javax.swing.JScrollPane();
        drawingArea2 = new br.usp.ime.faguilar.guis.DrawingArea();
        jPanel3 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        log = new javax.swing.JTextArea();
        jScrollPane1 = new javax.swing.JScrollPane();
        fileNames = new javax.swing.JList();

        setLayout(new java.awt.BorderLayout());

        jSplitPane1.setDividerLocation(150);

        jPanel2.setLayout(new java.awt.BorderLayout());

        jPanel5.setLayout(new java.awt.BorderLayout());

        jSplitPane2.setDividerLocation(500);
        jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        jPanel6.setLayout(new java.awt.BorderLayout());

        jButton1.setText("run");
        jButton1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButton1MouseClicked(evt);
            }
        });

        distanceFilter.setText("Distance filter");

        mstFilter.setText("MST filter");

        showMST.setText("Show MST");
        showMST.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                showMSTMouseClicked(evt);
            }
        });

        useTree.setText("Use Tree");

        org.jdesktop.layout.GroupLayout jPanel4Layout = new org.jdesktop.layout.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .add(distanceFilter)
                .add(55, 55, 55)
                .add(mstFilter)
                .add(36, 36, 36)
                .add(showMST)
                .add(44, 44, 44)
                .add(useTree)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 189, Short.MAX_VALUE)
                .add(jButton1)
                .add(21, 21, 21))
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jButton1)
                    .add(distanceFilter)
                    .add(mstFilter)
                    .add(showMST)
                    .add(useTree))
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel6.add(jPanel4, java.awt.BorderLayout.NORTH);

        org.jdesktop.layout.GroupLayout drawingArea2Layout = new org.jdesktop.layout.GroupLayout(drawingArea2);
        drawingArea2.setLayout(drawingArea2Layout);
        drawingArea2Layout.setHorizontalGroup(
            drawingArea2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 3630, Short.MAX_VALUE)
        );
        drawingArea2Layout.setVerticalGroup(
            drawingArea2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 468, Short.MAX_VALUE)
        );

        jScrollPane3.setViewportView(drawingArea2);

        jPanel6.add(jScrollPane3, java.awt.BorderLayout.CENTER);

        jSplitPane2.setTopComponent(jPanel6);

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Results"));
        jPanel3.setLayout(new java.awt.BorderLayout());

        log.setBackground(new java.awt.Color(0, 0, 0));
        log.setColumns(20);
        log.setForeground(new java.awt.Color(255, 255, 255));
        log.setRows(5);
        jScrollPane2.setViewportView(log);

        jPanel3.add(jScrollPane2, java.awt.BorderLayout.CENTER);

        jSplitPane2.setBottomComponent(jPanel3);

        jPanel5.add(jSplitPane2, java.awt.BorderLayout.CENTER);

        jPanel2.add(jPanel5, java.awt.BorderLayout.CENTER);

        jSplitPane1.setRightComponent(jPanel2);

        fileNames.setBackground(new java.awt.Color(0, 0, 0));
        fileNames.setForeground(new java.awt.Color(255, 255, 255));
        fileNames.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                fileNamesValueChanged(evt);
            }
        });
        jScrollPane1.setViewportView(fileNames);

        jSplitPane1.setLeftComponent(jScrollPane1);

        add(jSplitPane1, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

    private void fileNamesValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_fileNamesValueChanged
        // TODO add your handling code here:
        if(!evt.getValueIsAdjusting()){
            int selectedIndex = fileNames.getSelectedIndex();
            SelectedFileName = (String) fileNames.getModel().getElementAt(selectedIndex);
            showMathExpression();
//            executeSegmentationAndClassification();
//            updateMathExpression();
        }
    }//GEN-LAST:event_fileNamesValueChanged

    private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jButton1MouseClicked
        // TODO add your handling code here:
        executeSegmentationAndClassification();
//        updateMathExpression();
    }//GEN-LAST:event_jButton1MouseClicked

    private void showMSTMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_showMSTMouseClicked
        // TODO add your handling code here:
        if(fileSelected){
            drawingArea2.getDrawingObject().setDrawGraph(showMST.isSelected());
            drawingArea2.repaint();
        }
    }//GEN-LAST:event_showMSTMouseClicked

    
    private void updateMathExpression(){
//            int selectedIndex = fileNames.getSelectedIndex();
//            String selectedFileName = (String) fileNames.getModel().getElementAt(selectedIndex);
//            InkMLInput inkMlInput = new InkMLInput();
//            ArrayList<DStroke> strokes = inkMlInput.extractStrokesFromInkMLFile(
//                    INKML_DIR+selectedFileName);
//            strokes = PreprocessingAlgorithms.preprocessStrokes(strokes);
//            EdgeWeightedGraph StrokeSetToEdgeWeightedGraph =
//                MathExpressionGraph.StrokeSetToEdgeWeightedGraph(strokes);
//
//            KruskalMST mst = new KruskalMST(StrokeSetToEdgeWeightedGraph);
//            double meandistance = 0;
//            double alpha = 1;
//            for(Edge e: mst.edges())
//                meandistance += e.weight();
//            meandistance = alpha*(meandistance / StrokeSetToEdgeWeightedGraph.V() - 1);
//            boolean filterByDistance = distanceFilter.isSelected();
//            segmentation.setTruncateByDistance(filterByDistance);
//            segmentation.setMaxDistanceBetweenStrokes(meandistance);
//            boolean filterByMST = mstFilter.isSelected();
//            segmentation.setTruncateByMST(filterByMST);
//            segmentation.setMst(mst);
//            segmentation.part(strokes);
//
////            System.out.println(segmentation.getResult());
////            SegmentationResult resultClass = segmentation.getResult();
////            System.out.println(resultClass);
//
//            GraphicalStrokeKruskalMST graphicalObject =
//                    new GraphicalStrokeKruskalMST();
//            graphicalObject.setMst(mst);
//            graphicalObject.setStrokes(strokes);
//            GMathExpression expression = (GMathExpression) segmentation.getPartitionAsDMathExpression();
//            expression.setDrawnWithBBox(true);
//            expression.setDrawnWithLabels(true);
//            graphicalObject.setMathExpression(expression);
//            this.drawingArea2.setDrawingObject(graphicalObject);
//
//            drawingArea2.repaint();
//            String logResult = "Number of symbol evaluations: " +
//                    String.valueOf(segmentation.getNumberOfSymbolEvaluations());
//            addResultToLog(logResult);
    }

    private void executeSegmentationAndClassification(){
        double meandistance = 0;
        double filterMaxDistance;
        double alpha = .7;
        double beta = 0.5;
        for(Edge e: mst.edges())
            meandistance += e.weight();
        meandistance = meandistance / (StrokeSetToEdgeWeightedGraph.V() - 1);
        filterMaxDistance = alpha * meandistance;
        double mindistance = beta * meandistance;
        if(useTree.isSelected())
            segmentation =  new TreeSearchSegmentation();
        else
            segmentation =  new Segmentation();
        segmentation.setMinDist(mindistance);
        segmentation.setClassifier(classifier);
        boolean filterByDistance = distanceFilter.isSelected();
        segmentation.setTruncateByDistance(filterByDistance);
        segmentation.setMaxDistanceBetweenStrokes(filterMaxDistance);
        boolean filterByMST = mstFilter.isSelected();
        segmentation.setTruncateByMST(filterByMST);
        segmentation.setMst(mst);
        segmentation.part(strokes);

        GMathExpression expression = (GMathExpression) segmentation.getPartitionAsDMathExpression();

        //to show inkml
//        MathExpressionSample sample=new MathExpressionSample(
//        "id model",
//        "nickname",expression);
//        sample.setTextualRepresentation(null);
//        sample.setCategory("cat");
//
//        InkMLExpression inkMlExpression = new InkMLExpression();
//        inkMlExpression.setGroundTruthExpression(sample.getTextualRepresentation());
//        inkMlExpression.setSampleExpression(sample);
//        inkMlExpression.setTimeStampIncluded(false);
//        inkMlExpression.generateInkML();
//
//        String inkmlTex = inkMlExpression.getInkmlText();
////            count++;
//        FilesUtil.write(INKML_DIR + SelectedFileName.substring(0, SelectedFileName.length() - 6)
//                + "-res.inkml", inkmlTex);
////        FilesUtil.write(EvaluationView.INKML_CROHME_2012_TEST_DIR + SelectedFileName.substring(0, SelectedFileName.length() - 6)
////                + "-res.inkml", inkmlTex);

        // end to show inkml
        expression.setDrawnWithBBox(true);
        expression.setDrawnWithLabels(true);
        drawingArea2.getDrawingObject().setMathExpression(expression);
        drawingArea2.getDrawingObject().setDrawType(GraphicalStrokeKruskalMST.DRAW_TYPE_EXPRESSION);
        drawingArea2.repaint();
        String logResult = "Number of symbol evaluations: " +
        String.valueOf(segmentation.getNumberOfSymbolEvaluations());
        addResultToLog(logResult);
        
//        TO DO STRUCTURAL ANALISYS
        BSTBuilder parser = new BSTBuilder();
        
        parser.buildBST(expression, classifier);
        addResultToLog(parser.treeString());
        addResultToLog(parser.labelGraph());
//        System.out.println(parser.treeString());
//        System.out.println(parser.labelGraph());
//        ENS STRUCTURAL ANALISYS
    }

    private void showMathExpression(){
        String inkmlFileName = SelectedFileName;
        if(!fileSelected){
            fileSelected = true;
            if(drawingArea2.getDrawingObject() == null){
            GraphicalStrokeKruskalMST graphicalObject =
                new GraphicalStrokeKruskalMST();
            drawingArea2.setDrawingObject(graphicalObject);
            }
        }
        InkMLInput inkMlInput = new InkMLInput();
        strokes = inkMlInput.extractStrokesFromInkMLFile(
                MathRecognitionFiles.INKML_DIR + inkmlFileName);
//                INKML_CROHME_2012_TEST_DIR + inkmlFileName);
//        strokes = inkMlInput.extractStrokesFromInkMLFile(
//                EvaluationView.INKML_CROHME_2012_TEST_DIR + inkmlFileName);
        strokes = PreprocessingAlgorithms.preprocessStrokes(strokes);
//        for (DStroke dStroke : strokes) {
//            ArrayList<Point2D> nPoints = PreprocessingAlgorithms.getNPoints(dStroke, 10);
//            dStroke.clear();
//            for (Point2D point2D : nPoints) {
//                dStroke.addCheckingBoundingBox(new TimePoint(point2D.getX()
//                        , point2D.getY(), -1) );
//            }
//        }
        StrokeSetToEdgeWeightedGraph =
            MathExpressionGraph.StrokeSetToEdgeWeightedGraph(strokes);
        
        mst = new KruskalMST(StrokeSetToEdgeWeightedGraph);
//        printShortEdges();
        
        drawingArea2.getDrawingObject().setMst(mst);
        drawingArea2.getDrawingObject().setStrokes(strokes);
        drawingArea2.getDrawingObject().setDrawType(GraphicalStrokeKruskalMST.DRAW_TYPE_STROKES);
//        this.drawingArea2.setDrawingObject(drawingArea2.getDrawingObject());

        drawingArea2.repaint();
    }
    
    private void printShortEdges(){
        double distanceThreashold = 0;
        double alpha = 0.8;
        System.out.println("Short edges:");
        for(Edge e: mst.edges())
            distanceThreashold += e.weight();
        distanceThreashold = alpha*(distanceThreashold / StrokeSetToEdgeWeightedGraph.V() - 1);
        for(Edge e: mst.edges()){
            if(e.weight() < distanceThreashold)
                System.out.printf("Edge (%d, %d) \n", e.either(), e.other(e.either()));
        }
    }

    
    private void addResultToLog(String stringResult){
        log.append(stringResult + "\n");
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JCheckBox distanceFilter;
    private br.usp.ime.faguilar.guis.DrawingArea drawingArea2;
    private javax.swing.JList fileNames;
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JTextArea log;
    private javax.swing.JCheckBox mstFilter;
    private javax.swing.JCheckBox showMST;
    private javax.swing.JCheckBox useTree;
    // End of variables declaration//GEN-END:variables

    

}
